import cv2
import numpy as np
import Cell

MAX_DISTANCE = 15
MAX_AREA_RATIO = 0.85
COMPACTNESS_RATIO_ROUND = 0.8
COMPACTNESS_RATIO_FLATTER = 1.2


"""
This module mainly for matching cells in previous frame with current frame:
we match the nearest cell within threshold, and the shape and area don't change too much
if this cell cannot match cells in previous, we view them as new cells, either detected new cell
or division cell.
"""

def cell_match(cells_marked, cells_unmarked):
    for pre_cell in cells_marked:
        usedId = {}
        for cur_cell in cells_unmarked:

            # Compare the change of point distance and the change of area between two frames
            dist = distance(pre_cell.get_centroid(), cur_cell.get_centroid())
            if dist < MAX_DISTANCE and pre_cell.get_id() not in usedId:
                if cur_cell.compactness / pre_cell.compactness < COMPACTNESS_RATIO_ROUND:
                    continue

                # If the ratio of the current cell area to the last cell is less than 0.8, it is considered that the
                # cell has already divided
                if cur_cell.get_area() / pre_cell.get_area() < MAX_AREA_RATIO \
                        and cur_cell.compactness / pre_cell.compactness > COMPACTNESS_RATIO_FLATTER:
                    cur_cell.is_splitting = pre_cell.is_splitting + 1
                else:
                    cur_cell.is_splitting = pre_cell.is_splitting

                cur_cell.register_id(pre_cell.get_id(), pre_cell.get_color())
                usedId[pre_cell.get_id()] = pre_cell.get_id()
                cur_cell.update_path(pre_cell.get_path())

    # assign new cell with id
    newId = Cell.get_max_id(cells_marked) + 1
    for cur_cell in cells_unmarked:
        if cur_cell.get_id() == -1:
            cur_cell.register_id(newId)
            newId += 1

    return cells_unmarked


# get the distance of 2 centroids
# Euclidean Distance is used
def distance(p1, p2):
    return np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)


def draw_path(img, cell_list):
    for c in cell_list:
        if len(c.path) > 1:
            for i in range(1, len(c.path)):
                p1 = c.path[i - 1][0], c.path[i - 1][1]
                p2 = c.path[i][0], c.path[i][1]
                cv2.line(img, p1, p2, (255, 0, 0), 1)
    return img
